/**
 * socket插件
 */
export default {
  install(vue){

    function SocketHandler(url) {
      // 基于H5原生api
      this.ws = new WebSocket(url);
      // 定义一个信号发射塔，用于发送事件
      this.tower = document.createElement('div');
    }

    SocketHandler.prototype = {
      // 订阅频道
      channels : {},
      // 反应堆（用于收集和分发socket的响应）
      reactions : {},
      // 缓存监听事件
      events : [],
      // 获取当前时间
      nowTime() {
        return new Date().getTime();
      },
      // 打开socket连接
      open(heartbeatTimeout) {
        this.ws.onopen = ()=>{
          console.log('WebSocket连接已建立');
          let heartbeatSendInterval = heartbeatTimeout / 2;
          this.lastSubscribeTime = this.nowTime();
          this.pingIntervalId = setInterval(()=>{
            let iv = this.nowTime() - this.lastSubscribeTime;
            // 超过一定时间自动与后台ping、pong  单位：秒
            if ((heartbeatSendInterval + iv) >= heartbeatTimeout) {
              this.send('ping');
            }
          }, heartbeatSendInterval);
        };
      },

      // 创建自定义事件
      createEvent(event, detail){
        let evt = document.createEvent('CustomEvent');
        evt.initCustomEvent(event, false, false, detail);
        return evt;
      },

      // 打开socket连接
      connect(heartbeatTimeout = 10000) {
        console.log('尝试连接WebSocket:', this.ws.url);
        this.open(heartbeatTimeout);
        this.message();
        this.close();
      },

      // 订阅消息 ch 为订阅的频道 id 为订阅唯一标识
      subscribe(ch, id, token) {
        if(this.ws.readyState == 1) {
          let obj = {};
          if(ch) {
            // 根据后端要求，构造正确的订阅消息格式
            obj.sub = ch;
            obj.id = id;
            if(token) obj.authorization = token;
            if(this.channels.hasOwnProperty(id)) {
              this.unsubscribe.apply(this, Object.values(this.channels[id]));
            }
            this.channels[id] = obj;
            this.reactions[ch] = this.createEvent(id);
            this.send(obj);
          }
        } else {
          // 如果连接未建立，等待一段时间后重试
          setTimeout(() => {
            if(this.ws.readyState == 1) {
              this.subscribe(ch, id, token);
            }
          }, 1000);
        }
      },

      // 监听订阅结果
      on(id, callback) {
        console.log('注册事件监听器:', id);
        let handler = function(e) {
          console.log('收到事件:', id, e.data);
          if(callback) callback(e.data, e);
        };
        this.tower.addEventListener(id, handler);
        let key = id + '_' + this.nowTime();
        this.events.push({key : key, handler: handler});
      },

      // 取消订阅
      unsubscribe(ch, id, token) {
        if(this.ws.readyState == 1) {
          let obj = {};
          if(ch) {
            obj.cancel = ch;
            obj.id = id;
            if(token) obj.authorization = token;
            if(this.channels.hasOwnProperty(id)) {
              delete this.channels[id];
              delete this.reactions[ch];
            }
            this.events = this.events.filter((v)=>{
              if(v.key.indexOf(id) !== -1) {
                // 失效ID解除监听
                this.tower.removeEventListener(id, v.handler);
              }else{
                return v;
              }
            });
            this.send(obj);
          }
        }
      },

      send(data){
        if(typeof data === 'object') {
          data = JSON.stringify(data);
        }
        try {
          this.ws.send(data);
        } catch (error) {
          console.error('发送WebSocket消息失败:', error);
        }
      },

      message() {
        this.ws.onmessage = (evt)=>{
          let data = evt.data;
          this.lastSubscribeTime = this.nowTime();
          if(data) {
            // 处理多个消息粘连的情况
            if (data.indexOf('}{') !== -1) {
              // 分离粘连的消息
              let messages = data.split('}{');
              for (let i = 0; i < messages.length; i++) {
                let msg = messages[i];
                if (i === 0) {
                  msg = msg + '}';
                } else if (i === messages.length - 1) {
                  msg = '{' + msg;
                } else {
                  msg = '{' + msg + '}';
                }
                this._processMessage(msg);
              }
            } else {
              this._processMessage(data);
            }
          }
        }
      },
      
      _processMessage(rawData) {
        let data;
        if(rawData !== 'pong') {
          try {
            data = JSON.parse(rawData);
          } catch (e) {
            console.error('解析WebSocket消息失败:', rawData, e);
            return;
          }
        } else {
          data = rawData;
        }
        
        // 处理订阅确认消息和包含tick数据的消息
        if(data.hasOwnProperty('subbed')) {
          // 如果订阅确认消息中包含tick数据，也进行处理
          if (data.result) {
            console.log('收到订阅确认消息，包含result字段:', data);
            try {
              let result = JSON.parse(data.result);
              console.log('解析result字段结果:', result);
              if (result.tick) {
                console.log('result中包含tick数据:', result.tick);
                // 构造一个标准的数据更新消息
                let tickData = {
                  ch: data.subbed,
                  tick: typeof result.tick === 'string' ? JSON.parse(result.tick) : result.tick,
                  ts: data.ts
                };
                console.log('构造的tickData:', tickData);
                this._dispatchTickData(tickData);
              }
            } catch (e) {
              console.error('处理订阅确认消息中的tick数据失败:', e);
            }
          }
          return;
        }
        
        // 处理实际的盘口数据
        if(typeof data === 'object' && data.hasOwnProperty('ch')) {
          console.log('收到盘口数据:', data);
          this._dispatchTickData(data);
        } else if(data.hasOwnProperty('event')){
          let e = this.reactions[data.event];
          if(e) {
            e.data = data;
            this.tower.dispatchEvent(e);
          }
        }
      },
      
      _dispatchTickData(data) {
        console.log('准备分发tick数据:', data);
        let e = this.reactions[data.ch];
        if(e) {
          console.log('找到对应的事件处理器:', data.ch);
          // 如果tick数据是字符串格式，需要解析它
          if (data.tick && typeof data.tick === 'string') {
            try {
              data.tick = JSON.parse(data.tick);
              console.log('解析后的tick数据:', data.tick);
            } catch (e) {
              console.error('解析tick数据失败:', e);
            }
          }
          e.data = data;
          console.log('触发事件:', data.ch);
          this.tower.dispatchEvent(e);
        } else {
          console.log('未找到对应的事件处理器:', data.ch);
        }
      },
      close(callback) {
        this.ws.onclose = (evt)=>{
          clearInterval(this.pingIntervalId);
          // 尝试重新连接
          setTimeout(() => {
            vue.prototype.$socket = new SocketHandler(process.env.SOCKET_URL);
            vue.prototype.$socket.connect();
            // 重新订阅之前的频道
            for (let id in this.channels) {
              if (this.channels.hasOwnProperty(id)) {
                let channel = this.channels[id];
                vue.prototype.$socket.subscribe(channel.sub, id, channel.authorization);
              }
            }
          }, 3000);
          if(callback) callback(evt, this.ws);
        }
      },

      // 错误处理
      error(callback) {
        this.ws.onerror = (evt) => {
          console.log('WebSocket发生错误:', evt);
          if(callback) callback(evt, this.ws);
        }
      }
    };
    let ws = new SocketHandler(process.env.SOCKET_URL);
    // 将socket实例赋值到Vue原型链上
    vue.prototype.$socket = ws;
    // 初始化连接
    ws.connect();
    // 添加错误处理
    ws.error((evt, ws) => {
      console.error('WebSocket连接错误:', evt, ws);
    });
  }
}